/*
  SenSignalGenerator
 
 Sensornet deterministic test signal generator.

 Created 8 September 2010
 By Manu Montejo

http://sensornetpilot.blogspot.com
 */

// CONFIGURATION
long SLOT_PERIOD  =200L; //millis  0.5 seconds
long OUTPUT_SAMPLING_RATE  = 10 * 1000L;  //millis  

// INPUT/OUPUT  
int  ledPin       = 13;    // LED connected to digital pin 13
int  digitalOut   = 12;
int  analogInput  =  1;

// INTERNAL VARIABLES
float minF = 500;
float maxF = 3500;
float frequency = maxF;
int voltage = 0;
int ledState = 0;

// The setup() method runs once, when the sketch starts
void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(digitalOut, OUTPUT);
  // debug
  Serial.begin(9600);
  Serial.println("sensignalgenerator version Beta 1.0/Build 20101005");
  //Serial.println("single-discrete-frequency encoding");
  //Serial.println("message-single-frequency encoding");
  Serial.println("message-amplitude encoding");
  //Serial.print("period (seconds):"); Serial.println(OUTPUT_SAMPLING_RATE/1000);
  Serial.print("slot period (ms):"); Serial.println(SLOT_PERIOD);
}

// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()                     
{
  ledDebug();
//  generateSingleFrequency();

// amplitude encoding
  frequency = frequency + 5;
  if (frequency > 3500)
    frequency = 501;
  generateAmplitudeMessage();
  generateAmplitudeMessage();
  generateAmplitudeMessage();
  
//  // increment voltage
//  voltage = voltage + 2;
//  if (voltage > 620)
//    voltage =100;
//  generateSingleFrequencyMessage();
//  generateSingleFrequencyMessage();
//  generateSingleFrequencyMessage();
  
//  long counter = 0;
//  // increment voltage
//  voltage = voltage + 20; if (voltage>999) voltage = 0;
//  // freq generation
//  do {
//    //generate3xFrequency(); counter = counter + SLOT_PERIOD * 5;
//    generateDigitalFrequency(); counter = counter + SLOT_PERIOD * 11;
//  Serial.print("counter:"); Serial.println(counter);
//  Serial.print("OUTPUT_SAMPLING_RATE:"); Serial.println(OUTPUT_SAMPLING_RATE);
//  } while ( counter < OUTPUT_SAMPLING_RATE);
}


// -----------------------------------------
// amplitude encoding
// -----------------------------------------

void generateAmplitudeMessage(){
  // definitions  
  long slot_duration = SLOT_PERIOD;
  int message_start_frequency = 3600;

  // message: 6 frequencies
  noTone(digitalOut); tone(digitalOut, message_start_frequency); delay(slot_duration);
  noTone(digitalOut); delay(slot_duration);
  for (int i=0; i < 6; i++){
    float f = frequency + 5*i;  noTone(digitalOut); tone(digitalOut, f); delay(slot_duration);
    noTone(digitalOut); delay(slot_duration/10);
//  Serial.print("f="); Serial.println(f);
  }
}



// -----------------------------------------
// message-single-frequency encoding
// -----------------------------------------

void generateSingleFrequencyMessage(){

  // definitions  
  long slot_duration = SLOT_PERIOD;
  int message_start_frequency = 3600;
  int message_separator_frequency = 3700;

  // message: 5 frequencies
  frequency = message_start_frequency;  noTone(digitalOut); tone(digitalOut, frequency); delay(slot_duration);
  for (int i=0; i < 6; i++){
    frequency =  voltage2FrequencyMessage(voltage)+5*i;  noTone(digitalOut); tone(digitalOut, frequency); delay(slot_duration);
//  Serial.print("generateSingleFrequencyMessage: voltage="); Serial.print(voltage);
//  Serial.print("f="); Serial.println(frequency);

    frequency = message_separator_frequency;  noTone(digitalOut); tone(digitalOut, frequency); delay(slot_duration);
}
  

}

int voltage2FrequencyMessage(int v){
  // 100-620units  500-3500Hz
  int f =500 +  (v-100) * (3500-500.0)/(620-100.0);
  return f;
}




// -----------------------------------------
// DIGITAL ENCODING
// -----------------------------------------
void debugPrintBits(int n){
  Serial.print(n); Serial.print(":"); 
  for (int i=0; i <= 10; i++){
    int b = bitRead(n,i);
    Serial.print(b);
  }
  Serial.println("");
}

void generateDigitalFrequency(){
  long time = SLOT_PERIOD;
  // freqs
  int f_A = 520;
  int f_B = 700;
  int f_C = 900;
  frequency = f_A;
  noTone(digitalOut); delay(time*0.1); tone(digitalOut, frequency); delay(time*0.8); noTone(digitalOut); delay(time*0.1);
//  Serial.print("Tone (Hz):"); Serial.println(frequency);
  for (int i=0; i < 10; i++){ // 10 bits => 1024
    int b = bitRead(voltage,i);
    if ( b == 0)
      frequency = f_B;   
    else
      frequency = f_C;   
  noTone(digitalOut); delay(time*0.1); tone(digitalOut, frequency); delay(time*0.8); noTone(digitalOut); delay(time*0.1);
//  Serial.print("Tone (Hz):"); Serial.println(frequency);
  }

}
void generate3xFrequency(){
  // increment voltage
  voltage = voltage + 20;
  if (voltage>999) voltage = 0;
  // generate 4 freq-slots  syncrho, F+500, F+1500, F2500
  long time = SLOT_PERIOD;
  // synchro freq 
  frequency = 440;
  noTone(digitalOut); delay(time/2);
  tone(digitalOut, frequency); delay(time);
  noTone(digitalOut); delay(time/2);
  // 500-1500 band
  frequency = 500 + voltage;
  noTone(digitalOut); delay(time*0.1); tone(digitalOut, frequency); delay(time*0.8); noTone(digitalOut); delay(time*0.1);
  // 1500-2500 band
  frequency = 1500 + voltage;
  noTone(digitalOut); delay(time*0.1); tone(digitalOut, frequency); delay(time*0.8); noTone(digitalOut); delay(time*0.1);
  // 2500-3500 band
  frequency = 2500 + voltage;
  noTone(digitalOut); delay(time*0.1); tone(digitalOut, frequency); delay(time*0.8); noTone(digitalOut); delay(time*0.1);
}

void generateSingleFrequency(){
//  calculateFrequency();
  calculateDiscreteFrequency();
  noTone(digitalOut);
  tone(digitalOut, frequency);
  long time = OUTPUT_SAMPLING_RATE;
  delay(time);
}


void ledDebug(){
  if (ledState == 0){
    ledState = 1;
  } else {
    ledState = 0;
  }
  digitalWrite(ledPin, ledState);
}

int findNearestMultiple(int number, int multiple){
  int nearest = number/multiple;
  nearest = nearest * multiple;
  int r = number % multiple;
  if ( r > multiple/2.0)
    nearest = nearest + multiple;
  //Serial.print("findNearestMultiple: n="); Serial.print(number); Serial.print(" m="); Serial.print(multiple); Serial.print(" nearest="); Serial.println(nearest);        
  return nearest;
}

void calculateDiscreteFrequency(){
  // increment voltage
  voltage = voltage + 2;
  if (voltage > 700)
    voltage =30;
    
  // discretize frequency  
  // voltage range: 200-3000 mV; 40-614 units
  if (voltage >=40 && voltage < 400) { // 500-1400 Hz;
    frequency = (voltage-40)*5/2;
    frequency = 500 + findNearestMultiple(frequency, 5);
  }
  if (voltage >=400 && voltage < 614) { // 
    frequency = (voltage-400)*20/2;
    frequency = 1400 + findNearestMultiple(frequency, 20);
  }
  //Serial.print("calculateDiscreteFrequency: voltage="); Serial.print(voltage); Serial.print(" mV="); Serial.print(voltage*5000.0/1024); Serial.print(" freq="); Serial.println(frequency);
}

void calculateFrequency(){
  //constantF();
  increaseStep();
  //Serial.print("frequency (Hz)=");Serial.println(frequency);
}

void constantF(){
  //frequency = 440; // A note 440 Hz
  frequency = 700;
}

void increaseStep(){
  int increment = 5;
  frequency = frequency + increment;
  if ( frequency > maxF)
   frequency = minF;
}


